import { omit } from 'lodash-unified'
import { defineStore } from 'pinia'
import { reactive, toRefs } from 'vue'
import type { RouteRecordRaw } from 'vue-router'

import type { IUserMenu } from '@/apis'
import { CONST_ROUTES } from '@/constants'
import { DefaultLayout, ParentLayout } from '@/layout'
import { constRoutes } from '@/router'

import store from '.'

const routeComponents = import.meta.glob('../views/**/*.tsx')
const loadComponent = (component: string) =>
  routeComponents[`../views/${component}.tsx`]

/**
 * 过滤菜单列表
 */
async function filterMenuList(menus: IUserMenu) {
  const list: any[] = []
  const hash = new Map<string, any>()
  const tree = [] as any[]

  // 填充路由组件和路由名称
  for (const menu of menus) {
    const temp = { ...menu }

    if (menu.component === 'DefaultLayout') {
      // @ts-ignore
      temp.component = DefaultLayout
    } else if (menu.component === 'ParentLayout') {
      // @ts-ignore
      temp.component = ParentLayout
    } else {
      const component = loadComponent(menu.component)

      if (component) {
        const module: any = await component()

        temp.name = menu.componentName || module.default.name
        // @ts-ignore
        temp.component = component
        temp.meta.noCache = !!menu.meta.noCache

        // 设置异步组件名称以支持缓存
        module.default.name = temp.name
      } else {
        console.warn('配置的页面不存在：', menu.component)
      }
    }

    list.push(temp)
  }

  // 列表转树形
  for (const v of list) {
    hash.set(v.key, v)
    const parent = hash.get(v.parentKey)
    const route = omit(v, ['key', 'parentKey'])

    if (!parent) {
      tree.push(route)
    } else {
      parent.children.push(route)
    }
  }

  return tree
}

export const usePermissionStore = defineStore('permission', () => {
  const state = reactive({
    routes: [] as RouteRecordRaw[],
    matched: [] as string[]
  })

  async function generate(menus: IUserMenu) {
    const accessedRoutes: RouteRecordRaw[] = await filterMenuList(menus)

    accessedRoutes.push({
      path: '/:pathMatch(.*)*',
      redirect: {
        path: CONST_ROUTES.ERROR,
        query: { status: 404 }
      }
    })

    state.routes = constRoutes.concat(accessedRoutes)

    return accessedRoutes
  }

  return {
    ...toRefs(state),
    generate
  }
})

export function usePermissionStoreHook() {
  return usePermissionStore(store)
}
